#include "RedisConpool.hpp"
#include "const.hpp"
#include <cstddef>
#include <hiredis/hiredis.h>
#include <iostream>
#include <memory>
#include <mutex>
#include <utility>
RedisConPool::RedisConPool() : _b_stop(false) {
  std::string host = config.get<std::string>("Redis.Host");
  int port = config.get<int>("Redis.Port");
  std::string passwd = config.get<std::string>("Redis.PassWord");
  std::size_t poolSiez = config.get<int>("Redis.PoolSize");
  for (int i = 0; i < poolSiez; ++i) {
    // 建立连接
    _connection.reset(redisConnect(host.c_str(), port));
    if (_connection.get() == NULL || _connection->err) {
      std::cout << "establish connection failed!" << std::endl;
      redisFree(_connection.get());
      continue;
    }
    // 认证
    // auto _reply = (redisReply *)redisCommand(_connection.get(), "AUTH %s",
    //                                          passwd.c_str());
    // if (_reply == nullptr) {
    //   std::cout << "认证失败" << std::endl;
    //   freeReplyObject(_reply);
    //   continue;
    // }
    // if (_reply->type == REDIS_REPLY_ERROR) {
    //   std::cout << "认证失败" << std::endl;
    //   freeReplyObject(_reply);
    //   continue;
    // }
    // freeReplyObject(_reply);
    _connections.push(std::move(_connection));
  }
}

std::unique_ptr<redisContext> RedisConPool::GetConnection() {
  std::unique_lock<std::mutex> lock(_mutex);
  // 等待池子中有连接 或者 已经停止
  _cond.wait(lock, [this] { return !_connections.empty() || _b_stop; });

  // 停止
  if (_b_stop) {
    // 清空所有连接
    while (!_connections.empty()) {
      redisFree(_connections.front().get());
      _connections.pop();
    }
    return nullptr;
  }
  auto con = std::move(_connections.front());
  _connections.pop();
  return con;
}

void RedisConPool::ReturnConnection(std::unique_ptr<redisContext> con) {
  std::unique_lock<std::mutex> lock(_mutex);
  if (_b_stop) {
    redisFree(con.get());
    return;
  }
  _connections.push(std::move(con));
  _cond.notify_one();
}

void RedisConPool::Close() {
  _b_stop = false;
  _cond.notify_all();
}